﻿using Microsoft.SharePoint;
using System;
using System.IO;
using System.Text;
using System.Web;
using System.Linq;
using System.Reflection;

public class FileManagerSharePointHandler : IHttpHandler
{
	public string IconDirectory
	{
		get
		{
			return GetFileManagerBasePath() + "images/fileicons/";
		}
	}

	public string[] imgExtensions = new string[] { "jpg", "png", "jpeg", "gif", "bmp" }; // Only allow this image extensions. [string]

	private bool IsImageExtension(string extension)
	{
		return imgExtensions.Any(e => e.Equals(extension, StringComparison.OrdinalIgnoreCase));
	}


	private string GetFolderInfo(string url, string path)
	{
		StringBuilder sb = new StringBuilder();
		int i = 0;
		sb.AppendLine("{");
		SPSecurity.RunWithElevatedPrivileges(delegate()
		{
			using (SPSite site = new SPSite(url))
			{
				using (SPWeb web = site.OpenWeb())
				{	
					SPFolder currentFolder = web.GetFolder(path);
					foreach (SPFolder subFolder in currentFolder.SubFolders)
					{
						if (subFolder.Properties.ContainsKey("vti_listname"))
						{
							if (i > 0)
							{
								sb.Append(",");
								sb.AppendLine();
							}

							sb.AppendLine("\"" + Path.Combine(path, subFolder.Name) + "\": {");
							sb.AppendLine("\"Path\": \"" + Path.Combine(path, subFolder.Name) + "/\",");
							sb.AppendLine("\"Filename\": \"" + subFolder.Name + "\",");
							sb.AppendLine("\"File Type\": \"dir\",");
							sb.AppendLine("\"Preview\": \"" + IconDirectory + "_Open.png\",");
							sb.AppendLine("\"Properties\": {");
							sb.AppendLine("\"Date Created\": \"" + DateTime.Parse(subFolder.Properties["vti_timecreated"].ToString()).ToLocalTime().ToString() + "\", ");
							sb.AppendLine("\"Date Modified\": \"" + DateTime.Parse(subFolder.Properties["vti_timelastmodified"].ToString()).ToLocalTime().ToString() + "\", ");
							sb.AppendLine("\"Height\": 0,");
							sb.AppendLine("\"Width\": 0,");
							sb.AppendLine("\"Size\": 0 ");
							sb.AppendLine("},");
							sb.AppendLine("\"Error\": \"\",");
							sb.AppendLine("\"Code\": 0	");
							sb.Append("}");

							i++;
						}
					}

					foreach (SPFile fileItem in currentFolder.Files)
					{
						string extension = fileItem.Name.Substring(fileItem.Name.LastIndexOf(".") + 1);
						if (i > 0)
						{
							sb.Append(",");
							sb.AppendLine();
						}

						sb.AppendLine("\"" + Path.Combine(path, fileItem.Name) + "\": {");
						sb.AppendLine("\"Path\": \"" + Path.Combine(path, fileItem.Name) + "\",");
						sb.AppendLine("\"Filename\": \"" + fileItem.Name + "\",");
						sb.AppendLine("\"File Type\": \"" + extension + "\",");

						if (IsImageExtension(extension))
						{
							sb.AppendLine("\"Preview\": \"" + Path.Combine(path, fileItem.Name) + "?width=64&height=64&crop=false" + "\",");
						}
						else
						{
							sb.AppendLine("\"Preview\": \"" + String.Format("{0}{1}.png", IconDirectory, extension) + "\",");
						}

						sb.AppendLine("\"Properties\": {");
						sb.AppendLine("\"Date Created\": \"" + DateTime.Parse(fileItem.Properties["vti_timecreated"].ToString()).ToLocalTime().ToString() + "\", ");
						sb.AppendLine("\"Date Modified\": \"" + DateTime.Parse(fileItem.Properties["vti_timelastmodified"].ToString()).ToLocalTime().ToString() + "\", ");

						if (IsImageExtension(extension) && fileItem.Properties.ContainsKey("vti_lastheight"))
						{
							sb.AppendLine("\"Height\": " + fileItem.Properties["vti_lastheight"].ToString() + ",");
							sb.AppendLine("\"Width\": " + fileItem.Properties["vti_lastwidth"].ToString() + ",");
						}

						sb.AppendLine("\"Size\": " + fileItem.Length.ToString() + " ");
						sb.AppendLine("},");
						sb.AppendLine("\"Error\": \"\",");
						sb.AppendLine("\"Code\": 0	");
						sb.Append("}");

						i++;
					}
				}
			}
		});

		sb.AppendLine();
		sb.AppendLine("}");

		return sb.ToString();
	}

	private string GetFileManagerBasePath()
	{
		AssemblyName assemblyName = Assembly.GetExecutingAssembly().GetName();
		return "/_wpresources/" + (assemblyName.Name + "/" + assemblyName.Version.ToString() + "__" + BitConverter.ToString(assemblyName.GetPublicKeyToken()).Replace("-", String.Empty) + "/ckeditor/filemanager/");
	}

	private string GetInfo(string url, string path)
	{
		StringBuilder sb = new StringBuilder();

		SPSecurity.RunWithElevatedPrivileges(delegate()
		{
			using (SPSite site = new SPSite(url))
			{
				using (SPWeb web = site.OpenWeb())
				{
					SPFile currentFile = null;
					try
					{
						currentFile = web.GetFile(path);
					}
					catch { }
					if (currentFile != null && currentFile.Item != null && currentFile.Item.Folder == null)
					{
						string extension = currentFile.Name.Substring(currentFile.Name.LastIndexOf(".") + 1);
						sb.AppendLine("{");
						sb.AppendLine("\"Path\": \"" + path + "\",");
						sb.AppendLine("\"Filename\": \"" + currentFile.Name + "\",");
						sb.AppendLine("\"File Type\": \"" + extension + "\",");

						if (IsImageExtension(extension))
						{
							sb.AppendLine("\"Preview\": \"" + path + "?width=250&height=600&crop=false" + "\",");
						}
						else
						{
							sb.AppendLine("\"Preview\": \"" + String.Format("{0}{1}.png", IconDirectory, extension) + "\",");
						}

						sb.AppendLine("\"Properties\": {");
						sb.AppendLine("\"Date Created\": \"" + DateTime.Parse(currentFile.Properties["vti_timecreated"].ToString()).ToLocalTime().ToString() + "\", ");
						sb.AppendLine("\"Date Modified\": \"" + DateTime.Parse(currentFile.Properties["vti_timelastmodified"].ToString()).ToLocalTime().ToString() + "\", ");

						if (IsImageExtension(extension) && currentFile.Properties.ContainsKey("vti_lastheight"))
						{
							sb.AppendLine("\"Height\": " + currentFile.Properties["vti_lastheight"].ToString() + ",");
							sb.AppendLine("\"Width\": " + currentFile.Properties["vti_lastwidth"].ToString() + ",");
						}

						sb.AppendLine("\"Size\": " + currentFile.Length.ToString() + " ");
						sb.AppendLine("},");
						sb.AppendLine("\"Error\": \"\",");
						sb.AppendLine("\"Code\": 0	");
						sb.AppendLine("}");
					}
					else
					{
						SPFolder currentFolder = null;
						try
						{
							currentFolder = web.GetFolder(path);
						}
						catch { }
						if (currentFolder != null)
						{
							sb.AppendLine("{");
							sb.AppendLine("\"Path\": \"" + path + "\",");
							sb.AppendLine("\"Filename\": \"" + currentFolder.Name + "\",");
							sb.AppendLine("\"File Type\": \"dir\",");
							sb.AppendLine("\"Preview\": \"" + IconDirectory + "_Open.png\",");
							sb.AppendLine("\"Properties\": {");
							sb.AppendLine("\"Date Created\": \"" + DateTime.Parse(currentFolder.Properties["vti_timecreated"].ToString()).ToLocalTime().ToString() + "\", ");
							sb.AppendLine("\"Date Modified\": \"" + DateTime.Parse(currentFolder.Properties["vti_timelastmodified"].ToString()).ToLocalTime().ToString() + "\", ");
							sb.AppendLine("\"Height\": 0,");
							sb.AppendLine("\"Width\": 0,");
							sb.AppendLine("\"Size\": 0 ");
							sb.AppendLine("},");
							sb.AppendLine("\"Error\": \"\",");
							sb.AppendLine("\"Code\": 0	");
							sb.AppendLine("}");
						}
					}
				}
			}
		});

		return sb.ToString();

	}

	private string Rename(string url, string path, string newName)
	{
		StringBuilder sb = new StringBuilder();

		SPSecurity.RunWithElevatedPrivileges(delegate()
		{
			using (SPSite site = new SPSite(url))
			{
				using (SPWeb web = site.OpenWeb())
				{
					web.AllowUnsafeUpdates = true;
					SPFile currentFile = null;
					try
					{
						currentFile = web.GetFile(path);
					}
					catch { }
					if (currentFile != null)
					{
						currentFile.MoveTo(currentFile.ParentFolder.Url + "/" + newName);

						sb.AppendLine("{");
						sb.AppendLine("\"Error\": \"No error\",");
						sb.AppendLine("\"Code\": 0,");
						sb.AppendLine("\"Old Path\": \"" + path + "\",");
						sb.AppendLine("\"Old Name\": \"" + path.Substring(path.LastIndexOf("/") + 1) + "\",");
						sb.AppendLine("\"New Path\": \"" + currentFile.ParentFolder.Url + "/" + newName + "\",");
						sb.AppendLine("\"New Name\": \"" + newName + "\"");
						sb.AppendLine("}");
					}
					else
					{
						SPFolder currentFolder = null;
						try
						{
							currentFolder = web.GetFolder(path);
						}
						catch { }
						if (currentFolder != null)
						{
							currentFolder.MoveTo(currentFolder.ParentFolder.Url + "/" + newName);

							sb.AppendLine("{");
							sb.AppendLine("\"Error\": \"No error\",");
							sb.AppendLine("\"Code\": 0,");
							sb.AppendLine("\"Old Path\": \"" + path + "\",");
							sb.AppendLine("\"Old Name\": \"" + path.Substring(path.LastIndexOf("/") + 1) + "\",");
							sb.AppendLine("\"New Path\": \"" + currentFolder.ParentFolder.Url + "/" + newName + "\",");
							sb.AppendLine("\"New Name\": \"" + newName + "\"");
							sb.AppendLine("}");
						}
					}
				}
			}
		});

		return sb.ToString();
	}

	private string Delete(string url, string path)
	{
		StringBuilder sb = new StringBuilder();

		SPSecurity.RunWithElevatedPrivileges(delegate()
		{
			using (SPSite site = new SPSite(url))
			{
				using (SPWeb web = site.OpenWeb())
				{
					web.AllowUnsafeUpdates = true;
					SPFolder currentFolder = null;
					try
					{
						currentFolder = web.GetFolder(path);
					}
					catch { }
					if (currentFolder != null)
					{
						currentFolder.Delete();
					}
					else
					{
						SPFile currentFile = null;
						try
						{
							currentFile = web.GetFile(path);
						}
						catch { }
						if (currentFile != null)
						{
							currentFile.Delete();
						}
					}
				}
			}
		});
		
		sb.AppendLine("{");
		sb.AppendLine("\"Error\": \"No error\",");
		sb.AppendLine("\"Code\": 0,");
		sb.AppendLine("\"Path\": \"" + path + "\"");
		sb.AppendLine("}");

		return sb.ToString();
	}

	private string AddFolder(string url, string path, string newFolder)
	{
		StringBuilder sb = new StringBuilder();

		SPSecurity.RunWithElevatedPrivileges(delegate()
		{
			using (SPSite site = new SPSite(url))
			{
				using (SPWeb web = site.OpenWeb())
				{
					web.AllowUnsafeUpdates = true;
					SPList list = web.GetList(url);
					string fileUrl = path.Substring(path.IndexOf(list.RootFolder.Url));
					fileUrl = (fileUrl.Substring(fileUrl.IndexOf("/") + 1).TrimEnd('/') + "/" + newFolder).TrimStart('/');
					string[] fileParts = fileUrl.Split('/');

					SPFolder fileFolder = list.RootFolder;
					SPFolder previousFolder = list.RootFolder;


					fileParts = fileParts.ToArray();

					foreach (string fileSubFolder in fileParts)
					{
						try
						{
							fileFolder = fileFolder.SubFolders.Cast<SPFolder>().Where(f => f.Name.Equals(fileSubFolder, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
						}
						catch { }

						if (fileFolder == null || !fileFolder.Exists)
						{
							fileFolder = previousFolder.SubFolders.Add(fileSubFolder);
							if (list.EnableModeration)
							{
								fileFolder.Item.Update();

								SPListItem folderListItem = fileFolder.Item;
								fileFolder.Item.ModerationInformation.Status = SPModerationStatusType.Approved;
								fileFolder.Item.Update();
							}
						}
						previousFolder = fileFolder;
					}
				}
			}
		});

		sb.AppendLine("{");
		sb.AppendLine("\"Parent\": \"" + path + "\",");
		sb.AppendLine("\"Name\": \"" + newFolder + "\",");
		sb.AppendLine("\"Error\": \"No Error\",");
		sb.AppendLine("\"Code\": 0");
		sb.AppendLine("}");

		return sb.ToString();
	}

	public void ProcessRequest(HttpContext context)
	{
		context.Response.ClearHeaders();
		context.Response.ClearContent();
		context.Response.Clear();

		string path = "";
		if(context.Request["path"] != null)
			path = "/" + context.Request["path"].TrimStart('/');
		else if(context.Request["currentpath"] != null)
			path = "/" + context.Request["currentpath"].TrimStart('/');
		
		string url = SPContext.Current.Site.Url.TrimEnd('/') + path;

		switch (context.Request["mode"])
		{
			case "getinfo":

				context.Response.ContentType = "plain/text";
				context.Response.ContentEncoding = Encoding.UTF8;

				context.Response.Write(GetInfo(url, path));

				break;
			case "getfolder":

				context.Response.ContentType = "plain/text";
				context.Response.ContentEncoding = Encoding.UTF8;

				context.Response.Write(GetFolderInfo(url, path));

				break;
			case "rename":

				context.Response.ContentType = "plain/text";
				context.Response.ContentEncoding = Encoding.UTF8;

				context.Response.Write(Rename(url, context.Request["old"], context.Request["new"]));

				break;
			case "delete":

				context.Response.ContentType = "plain/text";
				context.Response.ContentEncoding = Encoding.UTF8;

				context.Response.Write(Delete(url, path));

				break;
			case "addfolder":

				context.Response.ContentType = "plain/text";
				context.Response.ContentEncoding = Encoding.UTF8;

				context.Response.Write(AddFolder(url, path, context.Request["name"]));

				break;
			case "download":
				SPSecurity.RunWithElevatedPrivileges(delegate()
					{
						using (SPSite site = new SPSite(url))
						{
							using (SPWeb web = site.OpenWeb())
							{
								SPList list = web.GetList(url);
								SPFile fileDownload = web.GetFile(path);
								if (fileDownload != null)
								{
									context.Response.ContentType = "application/octet-steram";
									context.Response.AddHeader("Content-Disposition", "attachment; filename=" + context.Server.UrlPathEncode(fileDownload.Name));

									byte[] buffer = fileDownload.OpenBinary();
									int length = buffer.Length;
									context.Response.OutputStream.Write(buffer, 0, length);

									context.Response.Flush();
									context.Response.Close();
									//context.Response.Redirect(web.Url.TrimStart('/') + "/" + fileDownload.Url.TrimStart('/'));
								}
							}
						}
					});
				//context.Response.AddHeader("Content-Disposition", "attachment; filename=" + context.Server.UrlPathEncode(fi.Name));
				//context.Response.AddHeader("Content-Length", fi.Length.ToString());
				//context.Response.ContentType = "application/octet-stream";
				//context.Response.TransmitFile(fi.FullName);

				break;
			case "add":
				System.Web.HttpPostedFile file = context.Request.Files[0];

				SPSecurity.RunWithElevatedPrivileges(delegate()
				{
					using (SPSite site = new SPSite(url))
					{
						using (SPWeb web = site.OpenWeb())
						{
							web.AllowUnsafeUpdates = true;
							SPList list = web.GetList(url);
							
							string fileUrl = path.Substring(path.IndexOf(list.RootFolder.Url));
							fileUrl = (fileUrl.Substring(fileUrl.IndexOf("/") + 1).TrimEnd('/') + "/" + file.FileName).TrimStart('/');
							string fileName = "";
							string[] fileParts = fileUrl.Split('/');

							SPFolder fileFolder = list.RootFolder;
							SPFolder previousFolder = list.RootFolder;

							if (fileParts.Length > 1)
							{
								fileName = fileParts.Last();
								fileParts = fileParts.Take(fileParts.Length - 1).ToArray();

								foreach (string fileSubFolder in fileParts)
								{
									try
									{
										fileFolder = fileFolder.SubFolders.Cast<SPFolder>().Where(f => f.Name.Equals(fileSubFolder, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
									}
									catch { }

									if (fileFolder == null || !fileFolder.Exists)
									{
										fileFolder = previousFolder.SubFolders.Add(fileSubFolder);
										if (list.EnableModeration)
										{
											fileFolder.Item.Update();

											SPListItem folderListItem = fileFolder.Item;
											fileFolder.Item.ModerationInformation.Status = SPModerationStatusType.Approved;
											fileFolder.Item.Update();
										}
									}
									previousFolder = fileFolder;
								}
							}
							else
							{
								fileName = fileUrl;
							}

							if (fileFolder != null && fileFolder.Exists)
							{
								SPFile newFile = null;

								try
								{
									newFile = fileFolder.Files.Add(fileName, file.InputStream);
									newFile.Update();
								}
								catch
								{
									fileFolder.Files.Delete(fileName);
									newFile = fileFolder.Files.Add(fileName, file.InputStream);
									newFile.Update();
								}

								if (newFile != null && list.EnableModeration)
								{
									SPListItem newItem = newFile.Item;
									newItem.ModerationInformation.Status = SPModerationStatusType.Approved;
									newItem.Update();
								}
							}
						}
					}
				});

				context.Response.ContentType = "text/html";
				context.Response.ContentEncoding = Encoding.UTF8;

				StringBuilder sb = new StringBuilder();

				sb.AppendLine("{");
				sb.AppendLine("\"Path\": \"" + path + "\",");
				sb.AppendLine("\"Name\": \"" + Path.GetFileName(file.FileName) + "\",");
				sb.AppendLine("\"Error\": \"No Error\",");
				sb.AppendLine("\"Code\": 0");
				sb.AppendLine("}");

				System.Web.UI.WebControls.TextBox txt = new System.Web.UI.WebControls.TextBox();
				txt.TextMode = System.Web.UI.WebControls.TextBoxMode.MultiLine;
				txt.Text = sb.ToString();

				StringWriter sw = new StringWriter();
				System.Web.UI.HtmlTextWriter writer = new System.Web.UI.HtmlTextWriter(sw);
				txt.RenderControl(writer);

				context.Response.Write(sw.ToString());

				break;
			default:
				break;
		}
	}

	public bool IsReusable
	{
		get
		{
			return false;
		}
	}
}
